<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <title>Hyena Diva Studio v2.1 ⚡️</title>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>

  <style>

    :root {

      --bg-gradient: radial-gradient(circle at 20% 20%, #fff5ff 0%, #ffe3ff 35%, #f9f8ff 75%, #f4f7ff 100%);

      --accent: #7d00b9;

      --accent-light: rgba(125, 0, 185, 0.1);

      --text: #2d1038;

      --panel-bg: rgba(255, 255, 255, 0.95);

      --border: rgba(45, 16, 56, 0.15);

    }


    * { box-sizing: border-box; }


    body {

      margin: 0;

      height: 100vh;

      overflow: hidden;

      font-family: "Trebuchet MS", system-ui, sans-serif;

      background: var(--bg-gradient);

      color: var(--text);

      display: flex;

      flex-direction: column;

      user-select: none;

    }


    /* Loading */

    #loading-overlay {

      position: fixed; inset: 0; background: rgba(255,255,255,0.98); z-index: 9999;

      display: flex; flex-direction: column; align-items: center; justify-content: center;

      transition: opacity 0.5s ease;

    }

    #loading-overlay.hidden { opacity: 0; pointer-events: none; }

    .spinner {

      width: 40px; height: 40px; border: 4px solid #ddd; border-top-color: var(--accent);

      border-radius: 50%; animation: load-spin 1s linear infinite; margin-bottom: 1rem;

    }

    @keyframes load-spin { to { transform: rotate(360deg); } }


    /* --- 3-PANE LAYOUT --- */

    #app-layout {

      display: grid;

      grid-template-columns: 320px 1fr 300px;

      grid-template-rows: 1fr;

      height: 100vh;

      gap: 1px;

      background: var(--border);

    }


    .panel-col {

      background: var(--panel-bg);

      display: flex;

      flex-direction: column;

      height: 100%;

      overflow: hidden; 

    }


    .panel-content {

      padding: 1rem;

      overflow-y: auto;

      flex: 1;

      display: flex;

      flex-direction: column;

      gap: 1rem;

    }


    /* LEFT: Library */

    .library-header {

      padding: 1rem 1rem 0.5rem 1rem;

      background: var(--panel-bg);

      border-bottom: 1px solid var(--border);

      flex-shrink: 0;

    }

    

    .prop-search {

      width: 100%; padding: 0.6rem; border-radius: 8px; border: 1px solid var(--border);

      margin-bottom: 0.5rem; font-family: inherit; font-size: 0.9rem;

    }


    .category-tabs {

      display: flex; flex-wrap: wrap; gap: 0.25rem;

    }

    

    .category-tabs button {

      font-size: 0.7rem; padding: 0.3rem 0.6rem; border-radius: 12px;

      border: 1px solid var(--border); background: #fff; cursor: pointer;

      text-transform: capitalize;

    }

    .category-tabs button:hover { background: #eee; }

    .category-tabs button.is-active {

      background: var(--accent); color: white; border-color: var(--accent);

    }


    .tile-grid {

      display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 0.5rem;

    }


    .tile {

      border: 1px solid transparent; border-radius: 8px; padding: 0.25rem;

      background: #fff; cursor: pointer; text-align: center;

      transition: all 0.1s;

      box-shadow: 0 1px 2px rgba(0,0,0,0.05);

    }

    .tile:hover { transform: translateY(-2px); border-color: var(--accent); }

    .tile img { width: 100%; height: 70px; object-fit: contain; display: block; image-rendering: pixelated; }

    .tile span { display: block; font-size: 0.65rem; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.7; }


    /* CENTER: Stage */

    .stage-area {

      background: #e0e0e5;

      display: flex; flex-direction: column; align-items: center; justify-content: center;

      position: relative; overflow: hidden;

    }


    .stage-wrapper {

      position: relative;

      box-shadow: 0 20px 50px rgba(0,0,0,0.2);

      border-radius: 4px;

      overflow: hidden;

      border: 4px solid #fff;

      transition: width 0.3s ease, height 0.3s ease;

    }


    #stage {

      width: 100%; height: 100%;

      background: #333 center/cover no-repeat;

      position: relative;

      touch-action: none;

    }


    /* Independent Grid Overlay */

    #grid-overlay {

      position: absolute; inset: 0; pointer-events: none; z-index: 9999;

      background: linear-gradient(rgba(125,0,185,0.2) 1px, transparent 1px), linear-gradient(90deg, rgba(125,0,185,0.2) 1px, transparent 1px);

      background-size: 50px 50px;

      display: none;

    }


    /* Stage Toolbar */

    .stage-toolbar {

      position: absolute; bottom: 20px; 

      background: rgba(255,255,255,0.95); backdrop-filter: blur(4px);

      padding: 0.4rem; border-radius: 50px; border: 1px solid var(--border);

      display: flex; gap: 0.4rem; align-items: center;

      box-shadow: 0 4px 12px rgba(0,0,0,0.15);

      z-index: 100;

    }


    .dim-select {

      border: 1px solid var(--border); border-radius: 20px; padding: 0.3rem 0.6rem;

      font-size: 0.75rem; background: #fff; color: var(--text); cursor: pointer; outline: none;

    }

    

    .icon-btn {

      width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--border);

      background: #fff; display: flex; align-items: center; justify-content: center;

      cursor: pointer; font-size: 1.2rem; transition: transform 0.1s;

      position: relative;

    }

    .icon-btn:hover { background: var(--accent-light); color: var(--accent); transform: scale(1.05); }

    .icon-btn:active { transform: scale(0.95); }

    

    /* Tooltip */

    .icon-btn::after {

      content: attr(title); position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%);

      background: #2d1038; color: #fff; font-size: 0.7rem; padding: 4px 8px; border-radius: 4px;

      opacity: 0; pointer-events: none; transition: opacity 0.2s; white-space: nowrap;

    }

    .icon-btn:hover::after { opacity: 1; }


    /* RIGHT: Inspector */

    .inspector-header {

      font-size: 0.8rem; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;

      color: var(--accent); border-bottom: 2px solid var(--accent-light);

      padding-bottom: 0.5rem; margin-bottom: 0.5rem;

    }


    .inspector-group {

      background: #fff; border: 1px solid var(--border); border-radius: 8px;

      padding: 0.75rem; display: flex; flex-direction: column; gap: 0.75rem;

    }


    .control-row {

      display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.7rem; color: #555;

      font-weight: 600; text-transform: uppercase;

    }


    .compact-grid {

      display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem;

    }

    

    input[type=range] { 

      width: 100%; height: 4px; border-radius: 2px; -webkit-appearance: none; background: #ddd;

    }

    input[type=range]::-webkit-slider-thumb {

      -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; 

      background: var(--accent); cursor: pointer; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.2);

    }


    .nudge-grid {

      display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;

      width: 100px; margin: 0 auto;

    }

    .nudge-btn {

      padding: 4px; font-size: 1rem; border: 1px solid var(--border);

      background: #f8f8f8; border-radius: 4px; cursor: pointer;

    }

    .nudge-btn:hover { background: var(--accent-light); color: var(--accent); }


    .action-grid {

      display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;

    }

    .action-btn {

      padding: 8px; font-size: 0.7rem; background: var(--accent-light);

      border: 1px solid transparent; border-radius: 6px; color: var(--accent); font-weight: 700;

      cursor: pointer; text-transform: uppercase;

    }

    .action-btn:hover { background: var(--accent); color: white; }

    .action-btn.danger { background: #ffeebb; color: #a33; }

    .action-btn.danger:hover { background: #d00; color: white; }

    .action-btn.reset { background: #eee; color: #666; }

    .action-btn.reset:hover { background: #ccc; color: #333; }


    /* Stage Items */

    .stage-item {

      position: absolute; 

      transform-origin: center; 

      cursor: grab;

      touch-action: none; 

      user-select: none;

    }

    .stage-item img {

      display: block; width: 100%; height: auto; 

      pointer-events: none; 

      image-rendering: pixelated;

      filter: var(--f, none); opacity: var(--o, 1);

    }

    .stage-item.is-selected {

      outline: 2px dashed rgba(255,255,255,0.8);

      box-shadow: 0 0 0 2px var(--accent);

      z-index: 1000 !important; 

      animation: select-pulse 2s infinite; /* Polished active state */

    }

    .stage-item:active { cursor: grabbing; }


    @keyframes select-pulse {

      0%, 100% { box-shadow: 0 0 0 2px var(--accent); }

      50% { box-shadow: 0 0 8px 3px var(--accent); }

    }


    /* Animation Classes */

    .anim-float { animation: floaty var(--spd, 2s) ease-in-out infinite; }

    .anim-bob { animation: bob var(--spd, 1s) ease-in-out infinite alternate; }

    .anim-spin { animation: spin var(--spd, 4s) linear infinite; }

    .anim-pulse { animation: pulse var(--spd, 1s) ease-in-out infinite; }

    .anim-shimmer { animation: shimmer var(--spd, 2s) ease-in-out infinite; }


    @keyframes floaty { 0%,100% { transform: translate(-50%, -50%) translateY(0) rotate(var(--r)) scale(var(--sx), var(--sy)); } 50% { transform: translate(-50%, -50%) translateY(-15px) rotate(var(--r)) scale(var(--sx), var(--sy)); } }

    @keyframes bob { 0% { transform: translate(-50%, -50%) translateY(0) rotate(var(--r)) scale(var(--sx), var(--sy)); } 100% { transform: translate(-50%, -50%) translateY(8px) rotate(var(--r)) scale(var(--sx), var(--sy)); } }

    @keyframes spin { from { transform: translate(-50%, -50%) rotate(0deg) scale(var(--sx), var(--sy)); } to { transform: translate(-50%, -50%) rotate(360deg) scale(var(--sx), var(--sy)); } }

    @keyframes pulse { 0%, 100% { opacity: var(--o); } 50% { opacity: calc(var(--o) * 0.5); } }

    @keyframes shimmer { 0%,100% { filter: var(--f) drop-shadow(0 0 0 rgba(255,255,255,0)); } 50% { filter: var(--f) drop-shadow(0 0 10px rgba(255,255,255,0.8)); } }


    @media (max-width: 900px) {

      #app-layout {

        grid-template-columns: 1fr; grid-template-rows: 250px 400px 1fr;

        height: auto; overflow-y: auto;

      }

      .stage-wrapper { transform: scale(0.6); transform-origin: top center; margin-bottom: -200px; }

      .panel-content { overflow: visible; }

    }

  </style>

</head>

<body>


  <div id="loading-overlay">

    <div class="spinner"></div>

    <div id="loading-text">Reading Synaptic Folders...</div>

  </div>


  <div id="app-layout">

    

    <aside class="panel-col">

      <div class="library-header">

        <h3 style="margin:0 0 0.5rem 0;">Assets ⚡️</h3>

        <input type="search" id="prop-search" class="prop-search" placeholder="Search files..." autocomplete="off" />

        <div class="category-tabs" id="category-tabs"></div>

      </div>

      

      <div class="panel-content">

        <div id="library-status" style="font-size:0.8rem; opacity:0.6; margin-bottom:0.5rem;"></div>

        <div class="tile-grid" id="asset-list"></div>

        <button id="load-more" style="width:100%; margin-top:1rem; padding:0.5rem; display:none; border:none; background:#eee; cursor:pointer; border-radius:4px;">Load More</button>

      </div>

    </aside>


    <main class="stage-area">

      <div class="stage-wrapper" id="stage-wrapper" style="width: 800px; height: 600px;">

        <div id="stage">

           <div id="grid-overlay"></div>

        </div>

      </div>


      <div class="stage-toolbar">

        <select class="dim-select" id="stage-dim" title="Stage Dimensions">

            <option value="800x600">Classic (4:3)</option>

            <option value="1024x576">Widescreen (16:9)</option>

            <option value="500x800">Vertical (Mobile)</option>

        </select>

        <div style="width:1px; background:#ccc; margin:0 4px; height: 20px;"></div>

        <button class="icon-btn" id="clear-stage" title="Clear Stage">🗑️</button>

        <button class="icon-btn" id="grid-toggle" title="Toggle Grid"></button>

        <div style="width:1px; background:#ccc; margin:0 4px; height: 20px;"></div>

        <button class="icon-btn" id="copy-scene" title="Copy Scene to Clipboard">📋</button>

        <button class="icon-btn" id="paste-scene" title="Paste Scene from Clipboard">📥</button>

        <div style="width:1px; background:#ccc; margin:0 4px; height: 20px;"></div>

        <button class="icon-btn" id="save-scene" title="Save JSON File">💾</button>

        <button class="icon-btn" id="load-scene" title="Load JSON File">📂</button>

        <button class="icon-btn" id="export-img" title="Export as PNG Screenshot">📸</button>

        <input type="file" id="scene-input" hidden accept=".json">

      </div>

    </main>


    <aside class="panel-col">

      <div class="panel-content">

        <div class="inspector-header">Inspector</div>

        

        <div id="inspector-empty" style="text-align:center; padding:2rem; opacity:0.6; font-size:0.9rem;">

          Select a localized pattern to edit.

        </div>


        <div id="inspector-controls" hidden>

          <div style="font-weight:bold; margin-bottom:0.5rem; font-size:0.85rem; word-break:break-all;" id="selected-name">Item Name</div>


          <div class="inspector-group">

            <div class="compact-grid">

              <div class="control-row">

                <label>Size</label>

                <input type="range" id="size-range" min="10" max="300" value="100">

              </div>

              <div class="control-row">

                <label>Rotation</label>

                <input type="range" id="rot-range" min="-180" max="180" value="0">

              </div>

            </div>

            <div class="action-grid">

               <button class="action-btn" id="btn-flip">Flip H</button>

               <button class="action-btn" id="btn-center">Center</button>

            </div>

            <div class="nudge-grid" title="Use Arrow Keys on Keyboard to Nudge!">

              <div></div><button class="nudge-btn" id="n-up"></button><div></div>

              <button class="nudge-btn" id="n-left"></button><div style="font-size:10px;text-align:center;display:flex;align-items:center;justify-content:center;">MOVE</div><button class="nudge-btn" id="n-right"></button>

              <div></div><button class="nudge-btn" id="n-down"></button><div></div>

            </div>

          </div>


          <div class="inspector-group">

            <div class="compact-grid">

              <div class="control-row">

                <label>Opacity</label>

                <input type="range" id="op-range" min="0" max="100" value="100">

              </div>

              <div class="control-row">

                <label>Blur</label>

                <input type="range" id="blur-range" min="0" max="10" value="0">

              </div>

              <div class="control-row">

                <label>Brightness</label>

                <input type="range" id="bri-range" min="0" max="200" value="100">

              </div>

              <div class="control-row">

                <label>Shadow</label>

                <input type="range" id="shd-range" min="0" max="20" value="0">

              </div>

              <div class="control-row">

                <label>Hue</label>

                <input type="range" id="hue-range" min="-180" max="180" value="0">

              </div>

              <div class="control-row">

                <label>Saturation</label>

                <input type="range" id="sat-range" min="0" max="200" value="100">

              </div>

            </div>

            <button class="action-btn reset" id="btn-reset-fx">Reset Effects</button>

          </div>


          <div class="inspector-group">

            <div class="control-row">

              <label>Animation</label>

              <select id="anim-select" style="width:100%; padding:4px;">

                <option value="none">None</option>

                <option value="float">Float</option>

                <option value="bob">Bob</option>

                <option value="shimmer">Shimmer</option>

                <option value="pulse">Pulse</option>

                <option value="spin">Spin</option>

              </select>

            </div>

            <div class="control-row">

              <label>Speed</label>

              <input type="range" id="anim-speed" min="1" max="50" value="20">

            </div>

          </div>


          <div class="inspector-group">

            <div class="action-grid">

              <button class="action-btn" id="btn-front">To Front</button>

              <button class="action-btn" id="btn-back">To Back</button>

              <button class="action-btn" id="btn-clone">Duplicate</button>

              <button class="action-btn danger" id="btn-del">Delete</button>

            </div>

          </div>

        </div>

      </div>

    </aside>


  </div>


<script>

    /* =========================================

       CONFIG

       ========================================= */

    const GITHUB = { owner: "TheNabu222", repo: "entropic-ai", branch: "main" };

    const RAW_URL = `https://raw.githubusercontent.com/${GITHUB.owner}/${GITHUB.repo}/${GITHUB.branch}`;

    const API_URL = `https://api.github.com/repos/${GITHUB.owner}/${GITHUB.repo}/git/trees/${GITHUB.branch}?recursive=1`;


    const IGNORE_FOLDERS = ["_archive", "old", "wip", "debug", "navbar", "ui", "icons", "website", "_hdtv", "favicons", "logo"];

    

    // State

    let allAssets = [];

    let filteredAssets = [];

    let renderedCount = 0;

    let activeCategory = "backdrops"; 

    let selectedEl = null;

    let zIndexCounter = 100;


    const dom = {

        stageWrapper: document.getElementById('stage-wrapper'),

        stage: document.getElementById('stage'),

        gridOverlay: document.getElementById('grid-overlay'),

        assetList: document.getElementById('asset-list'),

        tabs: document.getElementById('category-tabs'),

        search: document.getElementById('prop-search'),

        loadMore: document.getElementById('load-more'),

        inspectorEmpty: document.getElementById('inspector-empty'),

        inspectorControls: document.getElementById('inspector-controls'),

        selectedName: document.getElementById('selected-name'),

        libStatus: document.getElementById('library-status')

    };


    /* =========================================

       DATA LOGIC 

       ========================================= */

    async function init() {

        try {

            const res = await fetch(API_URL);

            if (!res.ok) throw new Error("GitHub Limit");

            const data = await res.json();

            processAssetsByFolder(data.tree);

            renderUI();

            document.getElementById('loading-overlay').classList.add('hidden');

        } catch (e) {

            alert("Error loading assets from GitHub. You may have hit the hourly API limit. Try again shortly.");

            console.error(e);

            document.getElementById('loading-overlay').classList.add('hidden');

        }

    }


    function processAssetsByFolder(tree) {

        allAssets = tree

            .filter(file => file.path.match(/\.(png|jpg|jpeg|gif|webp)$/i))

            .filter(file => !IGNORE_FOLDERS.some(term => file.path.toLowerCase().includes(term)))

            .map(file => {

                const parts = file.path.split('/');

                const filename = parts.pop();

                

                let folderPath = parts.join('/');

                folderPath = folderPath.replace(/^cavebot\/assets\//, ""); 

                folderPath = folderPath.replace(/^assets\//, ""); 

                folderPath = folderPath.replace(/^image\//, ""); 

                

                const cleanParts = folderPath.split('/');

                let category = cleanParts[0] || "Misc";


                category = category.replace(/[_-]/g, " ").toLowerCase();


                let label = filename

                    .replace(/\.[^/.]+$/, "")

                    .replace(/[_-]/g, " ")

                    .replace(/cavebot/gi, "")

                    .replace(/^\d+/, "")

                    .trim();


                return {

                    id: file.path,

                    url: `${RAW_URL}/${file.path}`,

                    label: label || filename,

                    category: category,

                    fullPath: file.path

                };

            });

    }


    /* =========================================

       UI RENDERING

       ========================================= */

    function renderUI() {

        const cats = [...new Set(allAssets.map(a => a.category))].sort();

        

        dom.tabs.innerHTML = cats.map(c => 

            `<button onclick="setCategory('${c}')" class="${c === activeCategory ? 'is-active' : ''}">${c}</button>`

        ).join('');


        if (!cats.includes(activeCategory)) {

            activeCategory = cats.includes('backdrops') ? 'backdrops' : cats[0];

        }

        

        updateTabs();

        filterAssets();

    }


    function updateTabs() {

        const btns = dom.tabs.querySelectorAll('button');

        btns.forEach(b => {

            b.classList.toggle('is-active', b.innerText === activeCategory);

        });

    }


    window.setCategory = (cat) => {

        activeCategory = cat;

        updateTabs();

        filterAssets();

    }


    function filterAssets() {

        const term = dom.search.value.toLowerCase();

        filteredAssets = allAssets.filter(a => {

            const matchCat = a.category === activeCategory;

            const matchSearch = a.label.toLowerCase().includes(term);

            return matchCat && matchSearch;

        });


        dom.libStatus.innerText = `${filteredAssets.length} items`;

        renderedCount = 0;

        dom.assetList.innerHTML = '';

        renderNextBatch();

    }


    function renderNextBatch() {

        const batch = filteredAssets.slice(renderedCount, renderedCount + 50);

        if (batch.length === 0 && renderedCount === 0) {

            dom.assetList.innerHTML = '<div style="grid-column:1/-1;text-align:center;opacity:0.5;font-size:0.8rem;">No items</div>';

            dom.loadMore.style.display = 'none';

            return;

        }


        const html = batch.map(item => `

            <div class="tile" onclick="handleAssetClick('${item.id}')" title="${item.label}">

                <img src="${item.url}" loading="lazy">

                <span>${item.label}</span>

            </div>

        `).join('');

        

        dom.assetList.insertAdjacentHTML('beforeend', html);

        renderedCount += batch.length;

        dom.loadMore.style.display = renderedCount < filteredAssets.length ? 'block' : 'none';

    }


    dom.search.addEventListener('input', () => filterAssets());

    dom.loadMore.addEventListener('click', renderNextBatch);


    /* =========================================

       STAGE LOGIC

       ========================================= */

    window.handleAssetClick = (id) => {

        const asset = allAssets.find(a => a.id === id);

        if (!asset) return;


        if (asset.category.includes('backdrop')) {

            dom.stage.style.backgroundImage = `url("${asset.url}")`;

            dom.stage.dataset.bgId = id; 

        } else {

            spawnProp(asset);

        }

    };


    function spawnProp(asset, state = null) {

        const el = document.createElement('div');

        el.className = 'stage-item';

        

        // BUG FIX: Ensure new items spawn on top of loaded items.

        el.style.zIndex = state && state.z ? state.z : ++zIndexCounter;

        

        // Initial Position

        el.style.left = state ? state.x : '50%';

        el.style.top = state ? state.y : '50%';

        

        // State

        el.dataset.id = asset.id;

        el.dataset.s = state ? state.s : 100; 

        el.dataset.r = state ? state.r : 0;   

        el.dataset.flip = state ? state.flip : 1;

        el.dataset.anim = state ? state.anim : 'none';

        el.dataset.spd = state ? state.spd : 20;

        

        // Visuals

        el.dataset.op = state ? state.op : 100;

        el.dataset.bl = state ? state.bl : 0;

        el.dataset.hue = state ? state.hue : 0;

        el.dataset.sat = state ? state.sat : 100;

        el.dataset.bri = state ? state.bri : 100;

        el.dataset.shd = state ? state.shd : 0;


        const img = document.createElement('img');

        img.src = asset.url;

        img.draggable = false; 


        // BUG FIX: Prevent massive assets from taking over the screen

        img.onload = () => {

             let w = img.naturalWidth;

             let h = img.naturalHeight;

             const MAX_DIM = 400; // Cap initial visual size

             

             if (w > MAX_DIM || h > MAX_DIM) {

                 const ratio = Math.min(MAX_DIM / w, MAX_DIM / h);

                 w = w * ratio;

                 h = h * ratio;

             }


             el.style.width = w + 'px';

             el.style.height = h + 'px';

             updateVisuals(el); 

        };


        el.appendChild(img);

        dom.stage.appendChild(el);

        

        updateVisuals(el);

        selectItem(el);

        enableDrag(el);

    }


    function selectItem(el) {

        if (selectedEl) selectedEl.classList.remove('is-selected');

        selectedEl = el;

        

        if (el) {

            el.classList.add('is-selected');

            dom.inspectorEmpty.hidden = true;

            dom.inspectorControls.hidden = false;

            

            const asset = allAssets.find(a => a.id === el.dataset.id);

            dom.selectedName.innerText = asset ? asset.label : 'Unknown';

            syncInspector();

        } else {

            dom.inspectorEmpty.hidden = false;

            dom.inspectorControls.hidden = true;

        }

    }


    // Deselect if clicking blank stage

    dom.stage.addEventListener('pointerdown', (e) => {

        if(e.target === dom.stage || e.target === dom.gridOverlay) selectItem(null);

    });


    function enableDrag(el) {

        let isDragging = false;

        let startX, startY, initLeft, initTop;


        el.addEventListener('pointerdown', (e) => {

            e.preventDefault(); 

            e.stopPropagation();

            selectItem(el);

            isDragging = true;

            el.setPointerCapture(e.pointerId);

            startX = e.clientX;

            startY = e.clientY;

            initLeft = parseFloat(el.style.left) || el.offsetLeft;

            initTop = parseFloat(el.style.top) || el.offsetTop;

        });


        el.addEventListener('pointermove', (e) => {

            if (!isDragging) return;

            // Get bounding rect to account for responsive scaling

            const rect = dom.stage.getBoundingClientRect();

            const scaleX = dom.stage.offsetWidth / rect.width;

            const scaleY = dom.stage.offsetHeight / rect.height;


            const dx = (e.clientX - startX) * scaleX;

            const dy = (e.clientY - startY) * scaleY;


            el.style.left = `${initLeft + dx}px`;

            el.style.top = `${initTop + dy}px`;

        });


        el.addEventListener('pointerup', (e) => {

            isDragging = false;

            el.releasePointerCapture(e.pointerId);

        });

    }


    /* =========================================

       INSPECTOR

       ========================================= */

    function updateVisuals(el = selectedEl) {

        if (!el) return;

        

        const s = (el.dataset.s || 100) / 100;

        const r = el.dataset.r || 0;

        const f = el.dataset.flip || 1;

        el.style.setProperty('--r', `${r}deg`);

        el.style.setProperty('--sx', f * s);

        el.style.setProperty('--sy', s);

        

        if (el.dataset.anim === 'none') {

            el.style.transform = `translate(-50%, -50%) rotate(${r}deg) scale(${f * s}, ${s})`;

        } else {

            el.style.transform = ''; 

        }


        const bl = el.dataset.bl;

        const hue = el.dataset.hue;

        const sat = el.dataset.sat;

        const bri = el.dataset.bri;

        const shd = el.dataset.shd;

        

        const filterStr = `blur(${bl}px) hue-rotate(${hue}deg) saturate(${sat}%) brightness(${bri}%)`;

        const dropShadow = shd > 0 ? `drop-shadow(0 0 ${shd}px rgba(0,0,0,0.5))` : '';

        

        const img = el.querySelector('img');

        img.style.setProperty('--f', `${filterStr} ${dropShadow}`);

        img.style.setProperty('--o', el.dataset.op / 100);


        el.className = `stage-item is-selected anim-${el.dataset.anim}`;

        el.style.setProperty('--spd', `${(51 - el.dataset.spd) / 10}s`); 

    }


    function syncInspector() {

        if (!selectedEl) return;

        ['s','r','op','bl','hue','sat','bri','shd','spd'].forEach(k => {

            const input = document.querySelector(`input[id^="${k}"]`) || document.getElementById(`${k}-range`) || document.getElementById(`anim-speed`);

            if(input) input.value = selectedEl.dataset[k];

        });

        document.getElementById('anim-select').value = selectedEl.dataset.anim;

    }


    const bindings = {

        'size-range': 's', 'rot-range': 'r', 'op-range': 'op', 'blur-range': 'bl',

        'hue-range': 'hue', 'sat-range': 'sat', 'bri-range': 'bri', 'shd-range': 'shd',

        'anim-speed': 'spd'

    };


    Object.keys(bindings).forEach(id => {

        document.getElementById(id).addEventListener('input', (e) => {

            if(selectedEl) {

                selectedEl.dataset[bindings[id]] = e.target.value;

                updateVisuals();

            }

        });

    });


    document.getElementById('anim-select').addEventListener('change', (e) => {

        if(selectedEl) { selectedEl.dataset.anim = e.target.value; updateVisuals(); }

    });


    document.getElementById('btn-flip').onclick = () => { if(selectedEl) { selectedEl.dataset.flip *= -1; updateVisuals(); } };

    document.getElementById('btn-center').onclick = () => { if(selectedEl) { selectedEl.style.left = '50%'; selectedEl.style.top = '50%'; } };

    document.getElementById('btn-reset-fx').onclick = () => {

        if(selectedEl) {

            Object.assign(selectedEl.dataset, { op:100, bl:0, hue:0, sat:100, bri:100, shd:0 });

            syncInspector(); updateVisuals();

        }

    };

    

    document.getElementById('btn-del').onclick = () => { if(selectedEl) { selectedEl.remove(); selectItem(null); } };

    document.getElementById('btn-clone').onclick = () => {

        if(selectedEl) {

            const asset = allAssets.find(a => a.id === selectedEl.dataset.id);

            if(asset) spawnProp(asset, { 

                ...selectedEl.dataset, 

                x: parseFloat(selectedEl.style.left) + 20 + 'px',

                y: parseFloat(selectedEl.style.top) + 20 + 'px',

                z: ++zIndexCounter // BUG FIX: Ensure clones spawn on top

            });

        }

    };

    document.getElementById('btn-front').onclick = () => { if(selectedEl) selectedEl.style.zIndex = ++zIndexCounter; };

    document.getElementById('btn-back').onclick = () => { if(selectedEl) selectedEl.style.zIndex = 0; };


    // Nudge Logic

    const nudge = (dx, dy) => {

        if(!selectedEl) return;

        selectedEl.style.left = (parseFloat(selectedEl.style.left) + dx) + 'px';

        selectedEl.style.top = (parseFloat(selectedEl.style.top) + dy) + 'px';

    };

    document.getElementById('n-up').onclick = () => nudge(0, -10);

    document.getElementById('n-down').onclick = () => nudge(0, 10);

    document.getElementById('n-left').onclick = () => nudge(-10, 0);

    document.getElementById('n-right').onclick = () => nudge(10, 0);


    /* =========================================

       TOOLBAR, SAVE/LOAD & EXPORT

       ========================================= */

    

    // Resize Stage Toggle

    document.getElementById('stage-dim').addEventListener('change', (e) => {

        const [w, h] = e.target.value.split('x');

        dom.stageWrapper.style.width = `${w}px`;

        dom.stageWrapper.style.height = `${h}px`;

    });


    document.getElementById('clear-stage').onclick = () => {

        Array.from(dom.stage.children).forEach(child => {

            if(child.id !== 'grid-overlay') child.remove();

        });

        selectItem(null);

    };


    // BUG FIX: Grid abstracted to a separate layer so it doesn't taint JSON Saves

    document.getElementById('grid-toggle').onclick = () => {

        const grid = dom.gridOverlay;

        grid.style.display = grid.style.display === 'block' ? 'none' : 'block';

    };


    // --- JSON Logic ---

    function getSceneData() {

        return {

            bgId: dom.stage.dataset.bgId || null,

            bgUrl: dom.stage.style.backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/, '$1'),

            items: Array.from(dom.stage.children)

                .filter(el => el.id !== 'grid-overlay')

                .map(el => ({

                    id: el.dataset.id,

                    x: el.style.left,

                    y: el.style.top,

                    z: el.style.zIndex,

                    ...el.dataset

                }))

        };

    }


    document.getElementById('save-scene').onclick = () => {

        const data = JSON.stringify(getSceneData(), null, 2);

        const blob = new Blob([data], {type: "application/json"});

        const a = document.createElement('a');

        a.href = URL.createObjectURL(blob);

        a.download = `cavebot-scene-${Date.now()}.json`;

        a.click();

    };


    document.getElementById('load-scene').onclick = () => document.getElementById('scene-input').click();

    document.getElementById('scene-input').onchange = (e) => {

        const file = e.target.files[0];

        if(!file) return;

        const reader = new FileReader();

        reader.onload = (ev) => loadSceneData(JSON.parse(ev.target.result));

        reader.readAsText(file);

    };


    function loadSceneData(data) {

        document.getElementById('clear-stage').click(); // Clean stage safely

        

        if(data.bgUrl && data.bgUrl !== 'none') {

             dom.stage.style.backgroundImage = `url("${data.bgUrl}")`;

             dom.stage.dataset.bgId = data.bgId;

        }

        

        if(data.items) {

            let maxZ = 100;

            data.items.forEach(item => {

                const asset = allAssets.find(a => a.id === item.id);

                if(asset) {

                    spawnProp(asset, item);

                    maxZ = Math.max(maxZ, parseInt(item.z) || 100);

                }

            });

            zIndexCounter = maxZ + 1; // BUG FIX: Keep counter higher than loaded assets

        }

    }


    // --- PNG Export Logic (NEW) ---

    document.getElementById('export-img').onclick = () => {

        selectItem(null); // Deselect before screenshot to remove bounding boxes

        const originalGridState = dom.gridOverlay.style.display;

        dom.gridOverlay.style.display = 'none'; // Hide grid for screenshot


        html2canvas(dom.stage, { 

            useCORS: true, 

            backgroundColor: null // Maintain transparent backgrounds if needed

        }).then(canvas => {

            const link = document.createElement('a');

            link.download = `scene-export-${Date.now()}.png`;

            link.href = canvas.toDataURL('image/png');

            link.click();

            dom.gridOverlay.style.display = originalGridState; // Restore grid

        });

    };


    // --- Clipboard Logic ---

    document.getElementById('copy-scene').onclick = () => {

        const data = JSON.stringify(getSceneData());

        navigator.clipboard.writeText(data).then(() => alert("Synaptic pattern copied to clipboard! ⚡️"));

    };


    document.getElementById('paste-scene').onclick = async () => {

        try {

            const text = await navigator.clipboard.readText();

            const data = JSON.parse(text);

            loadSceneData(data);

        } catch(e) {

            alert("Could not integrate scene. Invalid pattern data.");

        }

    };


    // Keyboard Integration

    document.addEventListener('keydown', (e) => {

        // Prevent deleting if typing in search box

        if(document.activeElement.tagName === 'INPUT') return; 


        if(e.key === 'Delete' || e.key === 'Backspace') {

            if(selectedEl) { selectedEl.remove(); selectItem(null); }

        }


        // Arrow Key Nudging

        if(selectedEl) {

            const step = e.shiftKey ? 15 : 2; // Hold shift for larger jumps

            if(e.key === 'ArrowUp') { e.preventDefault(); nudge(0, -step); }

            if(e.key === 'ArrowDown') { e.preventDefault(); nudge(0, step); }

            if(e.key === 'ArrowLeft') { e.preventDefault(); nudge(-step, 0); }

            if(e.key === 'ArrowRight') { e.preventDefault(); nudge(step, 0); }

        }

    });


    init();

</script>

</body>

</html>